<?php

/**
 * UpdateAction class file.
 * 
 * @author Kien.Tran <kien.tran@logigear.com>
 * @version 1.1
 */

abstract class LGAbstractAction extends CAction {

    /**
     * @var mixed the redirect URL processed by the class method.
     */
    private $_redirectTo = null;

    /**
     * @var string the name of the AJAX view.
     */
    public $ajaxView = '_form';

    /**
     * @var string a callback method in controller for additional processing.
     */
    public $callback = null;

    /**
     * @var string scripts which should be disabled on AJAX call.
     */
    public $disableScripts = array();

    /**
     * @var string flash messages prefix.
     */
    public $flashTypePrefix = '';

    /**
     * @var boolean is this an AJAX request.
     */
    protected $isAjaxRequest;

    /**
     * @var array user set messages for the action.
     */
    public $messages = array();

    /**
     * @var mixed the redirect URL set by the user.
     */
    public $redirectTo = null;

    /**
     * @var string message category used for Yii::t method.
     */
    public $tCategory = 'app';

    /**
     * @var string the name of the view.
     */
    public $view = null;
    public $modelClass = '';
    public $ajaxViewAuth;
    public $validateMethod = null;
    public $customAction = null;
    public $requiredPostRequest = false;

    /**
     * Initialize the action.
     */
    protected function init() {
	// Create default messages array
	$defaultMessages = array(
	    'error' => Yii::t($this->tCategory, 'There was an error while saving. Please try again.'),
	    'postRequest' => Yii::t($this->tCategory, 'Only post requests are allowed'),
	    'success' => Yii::t($this->tCategory, 'Successfully updated'),
	);

	// Merge with user set messages if array is provided
	if (is_array($this->messages)) {
	    $this->messages = CMap::mergeArray(
			    $defaultMessages, $this->messages);
	}
	else
	    throw new CException(Yii::t($this->tCategory, 'Action messages need to be an array'));

	// If view is not set, use action id for view
	if ($this->view === null)
	    $this->view = $this->id;

	// Check if this is an AJAX request
	$this->isAjaxRequest = Yii::app()->request->isAjaxRequest;
	if ($this->isAjaxRequest) {
	    // Create default array for scripts which should be disabled
	    $defaultDisableScripts = array(
		'jquery.js',
		'jquery.min.js',
		'jquery-ui.min.js'
	    );

	    // Merge with user set scripts which should be disabled
	    if (is_array($this->disableScripts)) {
		$this->disableScripts = CMap::mergeArray(
				$defaultDisableScripts, $this->disableScripts);
	    }
	    else
		throw new CException(Yii::t($this->tCategory, 'Disable scripts need to be an array.'));

	    // Disable scripts
	    foreach ($this->disableScripts as $script)
		Yii::app()->clientScript->scriptMap[$script] = false;

	    if ($this->requiredPostRequest) {
		// Allow only post requests

		if (!Yii::app()->request->isPostRequest) {
		    // Output JSON encoded content
		    echo CJSON::encode(array(
			'status' => 'failure',
			'content' => $this->messages['postRequest'],
		    ));

		    // Stop script execution
		    Yii::app()->end();
		}
	    }
	}
    }

    /**
     * Run the action.
     */
    public function run() {
	// Initialize the action
	$this->init();

	// Get the controller
	$controller = $this->getController();

	// Get the Model class
	//$modelClass = ucfirst( $controller->getId() );
	$modelClass = $this->modelClass;

	$models = $controller->loadModel();

	$msgReturn = NULL;

	//implement custom validate method
	if ($this->validateMethod !== null &&
		method_exists($controller, $this->validateMethod)) {
	    $msgReturn = $controller->{$this->validateMethod}($models);
	}

	if ($msgReturn == NULL) {

	    //Run customAction if it is not null
	    //Else run defaultAction
	    if ($this->customAction !== null &&
		    method_exists($controller, $this->customAction)) {
		$msgReturn = $controller->{$this->customAction}($models, $this);
	    } else {
		$msgReturn = $this->defaultAction($models);

		if ($msgReturn != NULL) {
		    //Run callback function if it's avaiable
		    if ($msgReturn->msgType == MsgType::SUCCESS) {
			if ($this->callback !== null &&
				method_exists($controller, $this->callback))
			    $controller->{$this->callback}($models, $this);
		    }
		}
	    }
	}

	$this->returnMessage($msgReturn, $models);
    }

    protected function returnMessage($msg, $models) {
	// Render update page using AJAX
	$controller = $this->getController();

	if ($this->isAjaxRequest) {
	    // Output JSON encoded content

	    if ($msg == NULL) {
		echo CJSON::encode(array(
		    'status' => 'render',
		    'content' => $controller->renderPartial($this->ajaxView, array(
			'model' => $models,
			'cancelUrl' => $this->getRedirectUrl($models->id)), true, true),
		));
	    } else {
		echo CJSON::encode(array(
		    'status' => $msg->msgType,
		    'content' => $msg->msgText,
		));
	    }

	    // Stop script execution
	    Yii::app()->end();
	}
	// Render update page without using AJAX
	else {
	    $controller->showMessage(MsgType::SUCCESS, $msg->msgText);

	    if (is_array($models)) {
		if ($this->redirectTo !== null) {
		    $controller->redirect($this->redirectTo);
		}
	    } else {
		$controller->render($this->view, array(
		    'model' => $models,
		    'cancelUrl' => $this->getRedirectUrl($models->id)));
	    }
	}
    }

    /*
     * 
     */

    protected abstract function defaultAction(&$models);

    /**
     * Returns whether this is an AJAX request.
     * @return boolean true if this is an AJAX request.
     */
    public function getIsAjaxRequest() {
	return $this->isAjaxRequest;
    }

    /**
     * Returns an URL for redirect.
     * @param int $id the id of the model to redirect to.
     * @return mixed processed redirect URL.
     */
    protected function getRedirectUrl($id) {
	// Process redirect URL
	if ($this->_redirectTo === null) {
	    // Use default redirect URL
	    if ($this->redirectTo === null)
		$this->_redirectTo = array('view', 'id' => $id);
	    // User set redirect URL is an array, check if id is needed
	    else if (is_array($this->redirectTo)) {
		// ID is set
		if (isset($this->redirectTo['id']))
		// ID needed, set it to the model id
		    if ($this->redirectTo['id'])
			$this->redirectTo['id'] = $id;
		    // ID is not needed, remove it from redirect URL
		    else
			unset($this->redirectTo['id']);

		// Set processed redirect URL
		$this->_redirectTo = $this->redirectTo;
	    }
	    // User set redirect URL is a string
	    else
		$this->_redirectTo = $this->redirectTo;
	}

	// Return processed redirect URL
	return $this->_redirectTo;
    }

}

?>